#!/usr/bin/env perl
use v5.10;
use strict;
use utf8; binmode $_, ":encoding(UTF-8)" for *STDIN, *STDOUT, *STDERR;
select(STDERR); $| = 1; select(STDOUT); # auto flush STDERR
use feature q(say);
use LWP::UserAgent;
use JSON;
use Encode;

# parse command-line arguments
our $CORENLP_SERVER_ENDPOINT          =              shift @ARGV;
our $num_input_columns                =              shift @ARGV;
our @input_column_ordinals_to_display = split /\s+/, shift @ARGV;
our @input_column_ordinals_to_nlp     = split /\s+/, shift @ARGV;
our @output_column_ordinals           =                    @ARGV;

# prepare things
my $json = JSON->new->allow_nonref;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new( POST => $CORENLP_SERVER_ENDPOINT );

my $generate_line_id = sub { join("\t", @{$_[0]}[@input_column_ordinals_to_display]) };
if (@input_column_ordinals_to_display eq 0) {
    # use line numbers if no id columns were specified
    my $line_no = 0; $generate_line_id = sub { ++$line_no; "L$line_no" };
}

while ( <STDIN> ) {
    # parse input TSJ line
    chomp; my @input_columns = split "\t", $_, $num_input_columns;
    my $line_id = $generate_line_id->(\@input_columns);
    say STDERR "Parsing $line_id";

    # ask CoreNLP to parse the requested columns
    my @nlp_results;
    for my $json_text (@input_columns[@input_column_ordinals_to_nlp]) {
        $req->content( Encode::encode_utf8($json->decode($json_text)) );
        # send HTTP request
        my $resp = $ua->request($req);
        if ($resp->is_success) {
            # and output result
            my $json_result = $resp->decoded_content;
            $json_result =~ s/\0//g; # XXX drop NULs inject by CoreNLP HTTP server
            push @nlp_results, $json_result;
        } else {
            # or show error message and keep a null result
            say STDERR "Parsing $line_id failed due to ERROR ", $resp->code, " ",
                $resp->message, ": ", $resp->decoded_content;
            push @nlp_results, "null";
        }
    }

    # output requested columns and NLP results in a TSJ line
    my @input_and_nlp_columns = (@input_columns, @nlp_results);
    my @output_columns = @input_and_nlp_columns[@output_column_ordinals];
    print shift @output_columns;
    print "\t", $_ foreach @output_columns;
    print "\n";
}
